package com.drcoffee.drcoffeemall.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.drcoffee.drcoffeemall.entry.Order;
import com.drcoffee.drcoffeemall.entry.Trade;
import com.drcoffee.drcoffeemall.mapper.OrderMapper;
import com.drcoffee.drcoffeemall.mapper.TradeMapper;
import com.drcoffee.drcoffeemall.service.AliPayService;
import com.drcoffee.drcoffeemall.util.AllPayVerifyUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public class AliAliPayServiceImpl implements AliPayService {
    @Autowired
    OrderMapper orderMapper;
    @Autowired
    TradeMapper tradeMapper;

    @Autowired
    AllPayVerifyUtil allPayVerifyUtil;

    /**
     * APPID，收款账号既是您的APPID对应支付宝账号
     */
    @Value("${alipay.app_id}")
    private String app_id;

    /**
     * 商户私钥，PKCS8格式RSA2私钥
     */
    @Value("${alipay.merchant_private_key}")
    private String merchant_private_key;

    /**
     * 支付宝公钥
     */
    @Value("${alipay.alipay_public_key}")
    private String alipay_public_key;

    /**
     * 服务器异步通知路径
     */
    @Value("${alipay.notify_url}")
    private String notify_url;

    /**
     * 页面跳转同步通知页面路径
     */
    @Value("${alipay.return_url}")
    private String return_url;

    /**
     * 签名方式
     */
    @Value("${alipay.sign_type}")
    private String sign_type;

    /**
     * 字符编码格式
     */
    @Value("${alipay.charset}")
    private String charset;

    /**
     * 支付宝网关
     */
    @Value("${alipay.gateway_url}")
    private String gateway_url;


    @Override
    public String aliPay(String order_code) {
        try {
            Order order = orderMapper.getOrderByCode(order_code);
            AlipayClient alipayClient = new DefaultAlipayClient(gateway_url, app_id, merchant_private_key, "json", charset, alipay_public_key, sign_type);
            AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
            request.setNotifyUrl(notify_url); // 异步接收地址
            request.setReturnUrl(return_url); // 同步跳转地址,付款成功后跳转到商户（这里的url就是商户的地址）
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", order.getCode()); // 订单号
            bizContent.put("total_amount", order.getOrder_total()); //支付金额
            bizContent.put("subject", "Dr.coffee 配件订单：" + order.getCode()); // 订单标题，不可使用特殊符号
            bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");// 电脑网站支付场景固定传值FAST_INSTANT_TRADE_PAY
            request.setBizContent(bizContent.toString());
            AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
            if (response.isSuccess()) {
                log.info("调用成功");
                return response.getBody();
            } else {
                log.error("调用失败");
                return response.getBody();
            }
        } catch (Exception e) {
            log.error("===================== aliPay()异常： =====================", e);
            return e.getMessage();
        }
    }

    @Override
    public void alipayReturn(HttpServletRequest request, String out_trade_no, String trade_no, String total_amount, String timestamp, HttpServletResponse response) {
        try {
            Map<String, String> params = getParamsMap(request);
            log.info("return params: {}", JSONObject.toJSON(params));

            // 验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(params, alipay_public_key, charset, sign_type);
            log.info("return signVerified: {}", signVerified);
            if (signVerified) {
                response.sendRedirect("http://mall.dr-coffee.com/order");
            } else {
                log.error("验证失败");
            }
        } catch (Exception e) {
            log.error("===================== alipayReturn()异常： =====================", e);
        }
    }

    @Override
    public String alipayNotify(HttpServletRequest request, String out_trade_no, String trade_no, String total_amount, String gmt_payment) {
        try {
            log.info("=============== 进入alipayNotify");
            log.info("订单号：" + out_trade_no);
            Map<String, String> params = getParamsMap(request);
            //验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(params, alipay_public_key, charset, sign_type);
            if (signVerified) {
                // TODO 验签成功后
                //按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验，校验成功后在response中返回success
                Order order = orderMapper.getOrderByCode(out_trade_no);
                BigDecimal ali_total_amount = new BigDecimal(total_amount);
                if (order == null || !order.getOrder_total().equals(ali_total_amount)) {
                    log.error("=============== order == null || !order.getOrder_total().equals(ali_total_amount)成立 返回fail");
                    return "fail";
                } else {
                    // 支付成功，更改订单状态
                    // 判断交易是否存在("防止重复调用")
                    Integer tradeNum = tradeMapper.getTradeNum(out_trade_no, "I");
                    if (tradeNum == 0) {
                        orderMapper.setStatus(out_trade_no, "2", "status_time_02", "");
                        // 存储交易记录
                        Trade trade = new Trade(null, out_trade_no, gmt_payment, trade_no, "", new BigDecimal(total_amount), "I", 2);
                        tradeMapper.saveTrade(trade);
                        orderMapper.setPayMethod(out_trade_no, 2);
                    }
                    return "success";
                }
            } else {
                // TODO 验签失败则记录异常日志，并在response中返回fail.\
                log.error("=============== 验签失败");
                return "fail";
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("===================== alipayNotify()异常： =====================", e);
            return "fail";
        }
    }

    @Override
    public void aliRefund(String order_code) {
        try {
            AlipayClient alipayClient = new DefaultAlipayClient(gateway_url, app_id, merchant_private_key, "json", charset, alipay_public_key, sign_type);
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            JSONObject bizContent = new JSONObject();
            // 根据订单编号查询交易记录
            Trade trade = tradeMapper.getTradeByOrder(order_code, "I");
            // 支付宝交易号
            bizContent.put("trade_no", trade.getTrade_no());
            // 退款金额
            bizContent.put("refund_amount", trade.getTrade_amount());
            // 退款请求号 标识一次退款请求，需要保证在交易号下唯一，如需部分退款，则此参数必传。(这里用订单号代替(只能退一次 即全额退款))
            bizContent.put("out_request_no", trade.getOrder_code());
            request.setBizContent(bizContent.toString());
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                log.info("===================== 退款成功 =====================");
                Date date = new Date();
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
                // 存储交易记录
                Trade refundTrade = new Trade(null, order_code, dateFormat.format(date), response.getTradeNo(), "", new BigDecimal(response.getRefundFee()), "O", 2);
                tradeMapper.saveTrade(refundTrade);
                orderMapper.setPayMethod(order_code, 2);
            } else {
                log.error("===================== 退款失败 =====================");
            }
        } catch (Exception e) {
            log.error("===================== aliRefund()异常： =====================", e);
        }
    }


    private Map<String, String> getParamsMap(HttpServletRequest request) {
        Map<String, String> params = new HashMap<>();
        Map requestParams = request.getParameterMap();
        for (Object object : requestParams.keySet()) {
            String name = (String) object;
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
            // valueStr = new String(valueStr.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            params.put(name, valueStr);
        }
        return params;
    }

}
